﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Xml;
using LunarSF.SHomeWorkshop.LunarMarkdownEditor.Widgets.MindMap;

namespace LunarSF.SHomeWorkshop.LunarMarkdownEditor.Widgets.MindMap
{
    /// <summary>
    /// 导图标题（节点）。
    /// </summary>
    public class MindMapTitle : AdornerDecorator, INotifyPropertyChanged
    {
        public MindMapTitle(MindMapView masterView, TreeElement element, TitleRole role)
        {
            this.masterView = masterView;
            TextOptions.SetTextFormattingMode(this, TextFormattingMode.Ideal);

            if (this.masterView != null)
            {
                //switch (this.masterView.Theme)
                //{
                //    case MindMapView.ViewTheme.Light:
                //        this.linkToParentPath.Stroke = Brushes.White;
                //        break;
                //    default:
                //        this.linkToParentPath.Stroke = Brushes.White;
                //        break;
                //}
                // 还是单独设置线色比较好。
                this.linkToParentPath.Stroke = this.masterView.TitleLinkStroke;
                this.Foreground = this.masterView.TitleDefaultForeground;
                this.role = role;
                RefreshTitleBackground();
            }

            this.mainTextBlock.Cursor = Cursors.Arrow;

            Binding cornerRadiusBinding = new Binding()
            {
                Source = this,
                Path = new PropertyPath(MindMapTitle.ActualHeightProperty),
                Converter = new HeightToRadiusConverter(),
            };
            this.backgroundRectangle.SetBinding(Rectangle.RadiusXProperty, cornerRadiusBinding);
            this.backgroundRectangle.SetBinding(Rectangle.RadiusYProperty, cornerRadiusBinding);

            Binding paddingBinding = new Binding()
            {
                Source = this.masterView,
                Converter = new DefaultFontSizeToPaddingConverter(),
                Path = new PropertyPath(MindMapView.TitleDefaultFontSizeProperty),
            };
            this.contentPanel.SetBinding(TextBlock.MarginProperty, paddingBinding);
            this.contentPanel.Children.Add(this.mainTextBlock);

            textStackPanel.Children.Add(contentPanel);
            textStackPanel.Children.Add(commentTextBlock);

            baseDockPanel.Children.Add(textStackPanel);
            this.baseGrid.Children.Add(this.backgroundRectangle);
            this.baseGrid.Children.Add(this.baseDockPanel);
            this.Child = this.baseGrid;

            //添加装饰器（选取框）
            AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(this.backgroundRectangle);
            selectedAdorner = new TitleSelectedAdorner(this.backgroundRectangle, this) { Visibility = System.Windows.Visibility.Collapsed, };
            adornerLayer.Add(selectedAdorner);

            layoutAdorner = new TitleLayoutAdorner(this.backgroundRectangle, this) { Visibility = System.Windows.Visibility.Collapsed, };
            adornerLayer.Add(layoutAdorner);

            leftArrowAdorner = new TitleLeftArrowAdorner(this.backgroundRectangle, this) { Visibility = System.Windows.Visibility.Collapsed, };
            rightArrowAdorner = new TitleRightArrowAdorner(this.backgroundRectangle, this) { Visibility = System.Windows.Visibility.Collapsed, };
            upArrowAdorner = new TitleUpArrowAdorner(this.backgroundRectangle, this) { Visibility = System.Windows.Visibility.Collapsed, };
            downArrowAdorner = new TitleDownArrowAdorner(this.backgroundRectangle, this) { Visibility = System.Windows.Visibility.Collapsed, };

            adornerLayer.Add(leftArrowAdorner);
            adornerLayer.Add(rightArrowAdorner);
            adornerLayer.Add(upArrowAdorner);
            adornerLayer.Add(downArrowAdorner);

            friendAdorner = new TitleFriendAdorner(this.backgroundRectangle, this) { Visibility = System.Windows.Visibility.Collapsed, };
            adornerLayer.Add(friendAdorner);

            childrenAdorner = new TitleChildAdorner(this.backgroundRectangle, this) { Visibility = Visibility.Collapsed, };
            adornerLayer.Add(childrenAdorner);

            linkAdorner = new TitleLinkAdorner(this.backgroundRectangle, this) { Visibility = Visibility.Collapsed, };
            adornerLayer.Add(linkAdorner);

            this.element = element;
            this.Build();

            this.PreviewMouseDown += Title_PreviewMouseDown;

            this.LayoutTransform = this.scaleTransform;
            this.baseGrid.MouseEnter += baseGrid_MouseEnter;
            this.baseGrid.MouseLeave += baseGrid_MouseLeave;

            this.linkToParentPath.Data = this.linkToParentPathGeometry;
            this.linkToParentPathGeometry.Figures.Add(this.linkToParentPathFigure);
            this.linkToParentPathFigure.Segments.Add(this.linkToParentBezierSegment);

        }

        public List<MindMapTitle> Children { get; set; } = null;

        void Title_PreviewMouseDown(object sender, MouseButtonEventArgs e)
        {
            ClickHandler(e);
        }

        void baseGrid_MouseLeave(object sender, MouseEventArgs e)
        {
            if (this.masterView != null)
            {
                RefreshTitleBackground();
                RefreshTitleForeground();
                //this.commentTextBlock.Foreground =
                //    this.MainTextBlock.Foreground = this.masterView.TitleDefaultForeground;
            }
            else
            {
                RefreshTitleBackground();
                RefreshTitleForeground();
                //this.commentTextBlock.Foreground =
                //    this.MainTextBlock.Foreground = Brushes.Black;
            }
        }

        void baseGrid_MouseEnter(object sender, MouseEventArgs e)
        {
            this.backgroundRectangle.Fill = new SolidColorBrush(Color.FromArgb(255, 145, 83, 0));
            this.commentTextBlock.Foreground =
                this.MainTextBlock.Foreground = Brushes.White;
        }

        private ScaleTransform scaleTransform = new ScaleTransform();

        private void ClickHandler(MouseButtonEventArgs e)
        {
            if (e.ClickCount == 2)
            {
                if (this.MasterView != null)
                {
                    //if (this.MasterView.DisplayTitle == this)
                    //{
                    //    e.Handled = true;
                    //    return;
                    //}
                    //else
                    //{
                    this.MasterView.DisplayMindMap(this.element);
                    //}

                    e.Handled = true;
                }
            }
            else if (e.ClickCount == 1)
            {
                if (this.MasterView != null)
                {
                    this.MasterView.SelectedTitle = this;
                    this.IsSelectedTitle = true;
                    e.Handled = true;

                    foreach (var ue in masterView.MainCanvas.Children)
                    {
                        var title = ue as MindMapTitle;
                        if (title == null || title == this) continue;

                        title.IsSelectedTitle = false;
                    }
                }
            }
        }

        private static Thickness borderInitilizeThickness = new Thickness(1);

        private Brush relationLineStroke = Brushes.BlueViolet;

        /// <summary>
        /// 连接此Title与上级Title之间的连接线的色彩。
        /// </summary>
        public Brush RelationLineStroke
        {
            get { return relationLineStroke; }
            set
            {
                relationLineStroke = value;
            }
        }

        /// <summary>
        /// 只有在默认加强视图下才会用此属性，其它所有视图下均只返回自身的尺寸。
        /// </summary>
        public Size DefaultNeedSize { get; set; }

        /// <summary>
        /// 加强版默认视图下，直接子级有的在左侧、有的在右侧，需要区分开来。
        /// </summary>
        public Direction LocationDirection { get; set; } = Direction.Right;

        /// <summary>
        /// 加强版默认视图才需要用到此属性。
        /// </summary>
        public enum Direction { Left, Right }

        private Grid baseGrid = new Grid();

        public Grid BaseGrid
        {
            get { return baseGrid; }
        }

        private Rectangle backgroundRectangle = new Rectangle();

        public Rectangle BackgroundRectangle
        {
            get { return backgroundRectangle; }
        }

        private DockPanel baseDockPanel = new DockPanel() { LastChildFill = false };

        /// <summary>
        /// 在baseStackPanel内部左侧。
        /// </summary>
        private StackPanel imgStackPanel = new StackPanel() { Orientation = Orientation.Horizontal };

        public StackPanel ImgStackPanel
        {
            get { return imgStackPanel; }
        }

        /// <summary>
        /// 在baseStackPanel内部的 contentPanel 右侧。
        /// </summary>
        private StackPanel textStackPanel = new StackPanel() { Orientation = Orientation.Vertical };

        private StackPanel contentPanel = new StackPanel() { Orientation = Orientation.Horizontal };

        private StackPanel iconsPanel = null;

        private TextBlock mainTextBlock = new TextBlock()
        {
            Foreground = Brushes.Black,
            TextWrapping = TextWrapping.Wrap,
            MaxWidth = 600,
            VerticalAlignment = VerticalAlignment.Center,
#if DEBUG
            Background = Brushes.Blue,
#endif
            //起初设置最大宽度为400，以便文本自动折行。2014年12月23日
            //最大宽度为什么是400呢？这是考虑到投影的需要
            //在8米长度的教室中，我近视眼可以看到150%倍放大的字，但已经很吃力。
            //而100%未放大的显示比例下，根本看不到。
            //而200%虽然有些浪费，但我能看见，后排学生一般也不成问题。
            //普通投影仪4：3的长宽比，一般均支持1024×768的分辨率，
            //宽度为500时，如果标题跨层级，在两种列表视图下，
            //不是上级横向显示不全，就是下级横向显示不全。
            //所以400是折衷后的数值。
        };

        private int borderWidth = 1;

        /// <summary>
        /// 默认值：1。
        /// </summary>
        public int BorderWidth
        {
            get { return borderWidth; }
            set
            {
                borderWidth = value;
                this.backgroundRectangle.StrokeThickness = borderWidth;// new Thickness(borderWidth);
            }
        }

        private bool isThemeTitle = false;
        /// <summary>
        /// 是否适应主题的标题。此种情形下，标题的背景色为透明色，前景色则为该主题的默认背景色。
        /// </summary>
        public bool IsThemeTitle
        {
            get { return this.isThemeTitle; }
            set
            {
                this.isThemeTitle = value;
                RefreshTitleBackground();
                RefreshTitleForeground();
            }
        }

        /// <summary>
        /// 保留这个字段目的是用在IsSelected属性改变时恢复边框色。
        /// </summary>
        public Brush borderBrush = Brushes.Transparent;

        /// <summary>
        /// 自定义边框色属性。对原有的BorderBrush进行了封装。
        /// 这个值并不一定等于MainBorder的BorderBrush，因为有些公式
        /// （如网格式）会有“自动边框色”。
        /// </summary>
        public Brush BorderBrush
        {
            get { return borderBrush; }
            set
            {
                this.borderBrush = value;

                if (value == null)
                {
                    this.backgroundRectangle.Stroke = Brushes.Transparent;
                }
                else
                {
                    this.backgroundRectangle.Stroke = value;
                }

                RfreshBorderBrush();
            }
        }

        public TextBlock MainTextBlock
        {
            get { return mainTextBlock; }
        }

        /// <summary>
        /// 根据当前演示的中心标题的中心点，计算出相对于此中心点的相对位置。等 Canvas 的宽、高确定后，再计算出实际左上角坐标。
        /// </summary>
        public double RelativePointX { get; set; }
        public double RelativePointY { get; set; }

        /// <summary>
        /// 实际左上角坐标。
        /// </summary>
        public double AbsolutePointXInCanvas { get; set; }
        public double AbsolutePointYInCanvas { get; set; }

        //注释文本块默认不显示。只有当存在注释文本时，才显示。
        private TextBlock commentTextBlock = new TextBlock()
        {
            Visibility = Visibility.Collapsed,
            //Opacity = 0.75,
            Foreground = Brushes.Green,
            TextWrapping = TextWrapping.Wrap,
            //MaxWidth = 364,//要考虑箭头空间，所以不能满400，但若要保持对齐，就不能在这里设置。
        };

        private Brush CommentForeground
        {
            get { return this.commentTextBlock.Foreground; }
            set
            {
                RefreshCommentForeground();
                OnPropertyChanged(this, new PropertyChangedEventArgs(Properties.Resources.x_TitleCommentForegroundTag));
            }
        }

        /// <summary>
        /// 注释文本块。
        /// </summary>
        public TextBlock CommentTextBlock
        {
            get { return commentTextBlock; }
        }

        public Brush TitleBackground
        {
            get { return this.backgroundRectangle.Fill; }//Background; }
            set
            {
                RefreshTitleBackground();
                OnPropertyChanged(this, new PropertyChangedEventArgs(Properties.Resources.x_TitleBackgroundTag));
            }
        }

        public void RefreshTitleForeground()
        {
            if (isThemeTitle)
            {
                this.mainTextBlock.Foreground = MasterView.TitleDefaultBackground;
            }
            else
            {
                this.mainTextBlock.Foreground = MasterView.TitleDefaultForeground;
            }
        }

        public void RefreshTitleBackground()
        {
            if (isThemeTitle)
            {
                this.backgroundRectangle.Fill = Brushes.Transparent;
            }
            else
            {
                switch (this.Role)
                {
                    case TitleRole.AncestorsTitle:
                        {
                            this.backgroundRectangle.Fill = MasterView.AncestorsTitleDefaultBackground;
                            break;
                        }
                    case TitleRole.ChildTitle:
                        {
                            this.backgroundRectangle.Fill = MasterView.ChildTitleDefaultBackground;
                            break;
                        }
                    default:
                        {
                            this.backgroundRectangle.Fill = MasterView.TitleDefaultBackground;
                            break;
                        }
                }
            }
        }

        public void RefreshSelectionBrush()
        {
            this.selectedAdorner.InvalidateVisual();
        }

        private void RefreshCommentForeground()
        {
            this.commentTextBlock.Foreground = MasterView.TitleDefaultCommentForegeound;
        }

        private void RfreshBorderBrush()
        {
            this.commentTextBlock.Foreground = MasterView.TitleDefaultBorderBrush;
        }

        public Brush Foreground
        {
            get { return this.mainTextBlock.Foreground; }
            set
            {
                RefreshTitleForeground();
                OnPropertyChanged(this, new PropertyChangedEventArgs(Properties.Resources.x_TitleForegroundTag));
            }
        }

        private TreeElement element;

        public TreeElement Element
        {
            get { return element; }
            set
            {
                element = value;
                Build();
            }
        }

        private void Build()
        {
            if (this.element == null) return;

            RefreshTitleForeground();
            RefreshDefaultFontSize();
            RefreshCommentForeground();
            RefreshTitleBackground();

            RfreshBorderBrush();
            RefreshText();
            RefreshArrows();

            RefreshChildrenStatus();
            RefreshJumpLinkStatus();
            RefreshContentType();
        }

        private void RefreshJumpLinkStatus()
        {
            if (this.IsFriendExist)
            {
                this.friendAdorner.Visibility = System.Windows.Visibility.Visible;
                this.friendAdorner.InvalidateVisual();
            }
            else
            {
                this.friendAdorner.Visibility = System.Windows.Visibility.Collapsed;
            }
        }

        private void RefreshChildrenStatus()
        {
            if (this.element.Children.Count > 0)
            {
                this.childrenAdorner.Visibility = System.Windows.Visibility.Visible;
                this.childrenAdorner.InvalidateVisual();
            }
            else
            {
                this.childrenAdorner.Visibility = System.Windows.Visibility.Collapsed;
            }
        }

        private void RefreshArrows()
        {
            // TODO: 暂时禁用标题的箭头标记，目前尚未想到怎么用它！2022.11.2
            this.leftArrowAdorner.Visibility =
                    this.rightArrowAdorner.Visibility =
                    this.upArrowAdorner.Visibility =
                    this.downArrowAdorner.Visibility = System.Windows.Visibility.Collapsed;
            return;

            // 备用代码，暂时没想到怎么用箭头！
            //if (this.element == null)
            //{
            //    this.leftArrowAdorner.Visibility =
            //        this.rightArrowAdorner.Visibility =
            //        this.upArrowAdorner.Visibility =
            //        this.downArrowAdorner.Visibility = System.Windows.Visibility.Collapsed;
            //    return;
            //}

            //if (this.element.ParentElement != null)
            //{
            //    this.leftArrowAdorner.Visibility = System.Windows.Visibility.Visible;
            //    this.leftArrowAdorner.InvalidateVisual();
            //}
            //else
            //{
            //    this.leftArrowAdorner.Visibility = System.Windows.Visibility.Collapsed;
            //}

            //if (this.element.Children.Count > 0)
            //{
            //    this.rightArrowAdorner.Visibility = System.Windows.Visibility.Visible;
            //    this.rightArrowAdorner.InvalidateVisual();
            //}
            //else
            //{
            //    this.rightArrowAdorner.Visibility = System.Windows.Visibility.Collapsed;
            //}

            //if (this.element.PreviewElements != null && this.element.PreviewElements.Count > 0)
            //{
            //    this.upArrowAdorner.Visibility = System.Windows.Visibility.Visible;
            //    this.upArrowAdorner.InvalidateVisual();
            //}
            //else
            //{
            //    this.upArrowAdorner.Visibility = System.Windows.Visibility.Collapsed;
            //}

            //if (this.element.NextElements != null && this.element.NextElements.Count > 0)
            //{
            //    this.downArrowAdorner.Visibility = System.Windows.Visibility.Visible;
            //    this.downArrowAdorner.InvalidateVisual();
            //}
            //else
            //{
            //    this.downArrowAdorner.Visibility = System.Windows.Visibility.Collapsed;
            //}
        }

        private void RefreshDefaultFontSize()
        {
            if (this.masterView == null) return;

            if (double.IsNaN(this.masterView.TitleDefaultFontSize))
            {
                this.mainTextBlock.SetResourceReference(TextBlock.FontSizeProperty, "title_default_font_size");
                this.commentTextBlock.SetResourceReference(TextBlock.FontSizeProperty, "title_default_font_size");
            }
            else
            {
                this.mainTextBlock.FontSize = this.masterView.TitleDefaultFontSize;
                this.commentTextBlock.FontSize = this.masterView.TitleDefaultFontSize;
            }
        }

        private void RefreshText()
        {
            var text = this.element.Content;
            if (text != null)
            {
                var pieces = Utils.Text.SplitToPiecesByRegex(@"\(:.*?:\)", text);
                if (pieces.Count <= 1)
                {
                    this.mainTextBlock.Text = text;
                }
                else
                {
                    if (this.iconsPanel != null)
                    {
                        this.iconsPanel.Children.Clear();
                    }

                    foreach (var piece in pieces)
                    {
                        if (piece.IsMartchText)
                        {
                            if (this.iconsPanel == null)
                            {
                                this.iconsPanel = new StackPanel() { Orientation = Orientation.Horizontal };
                                this.contentPanel.Children.Insert(0, this.iconsPanel);
                            }

                            var quickImageRelativePath = Globals.PathofWorkspaceImages + piece.SourceText.Substring(2, piece.SourceText.Length - 4);
                            if (quickImageRelativePath.LastIndexOf(".") < 0)
                            {
                                quickImageRelativePath += ".png";
                            }
                            var img = new Image() { Source = Globals.LoadBitmapImageFromFile(quickImageRelativePath), VerticalAlignment = VerticalAlignment.Center, };
                            if (this.masterView != null)
                            {
                                img.Height = this.masterView.TitleDefaultFontSize;
                            }
                            this.iconsPanel.Children.Add(img);
                        }
                        else
                        {
                            this.mainTextBlock.Inlines.Add(piece.SourceText);
                        }
                    }
                }
            }
            else
            {
                this.mainTextBlock.SetResourceReference(TextBlock.TextProperty, "title_default_text");
                //this.mainTextBlock.Text = TryFindResource("title_default_text") as string;
            }
        }

        public void RefreshContentType()
        {
            if(this.element == null)
            {
                this.linkAdorner.Visibility = Visibility.Collapsed;
                return;
            }

            switch (this.element.Type)
            {
                case TreeElementType.FileLink:
                case TreeElementType.ImageLink:
                    {
                        this.linkAdorner.InvalidateVisual();
                        this.linkAdorner.Visibility = Visibility.Visible;
                        break;
                    }
                default:
                    {
                        this.linkAdorner.Visibility = Visibility.Collapsed;
                        break;
                    }
            }
        }

        /// <summary>
        /// 设置点之后，要调用此方法才会生效。
        /// </summary>
        public void RefreshLine(Point? basePoint)
        {
            if (basePoint.HasValue)
            {
                this.LinkToParentPathFigure.StartPoint = basePoint.Value;
                this.linkToParentBezierSegment.Point1 = basePoint.Value;
                this.linkToParentBezierSegment.Point2 = basePoint.Value;
                this.linkToParentBezierSegment.Point3 = basePoint.Value;
            }
            else
            {
                this.LinkToParentPathFigure.StartPoint = LinkPointStart;
                this.linkToParentBezierSegment.Point1 = LinkPoint1;
                this.linkToParentBezierSegment.Point2 = LinkPoint2;
                this.linkToParentBezierSegment.Point3 = LinkPoint3;
            }
        }

        #region 实现INotifyPropertyChanged接口成员

        public event PropertyChangedEventHandler PropertyChanged;

        public void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(sender, e);
            }
        }

        #endregion

        #region 事件链接，用以通知视图重新布局。
        public event EventHandler<LayoutTypeChangedEventArgs> LayoutTypeChanged;

        private void OnLayoutTypeChanged(object sender, LayoutTypeChangedEventArgs e)
        {
            if (LayoutTypeChanged != null)
            {
                LayoutTypeChanged(sender, e);
            }
        }
        #endregion

        private TitleSelectedAdorner selectedAdorner;

        private TitleLayoutAdorner layoutAdorner;

        private TitleChildAdorner childrenAdorner;

        private TitleLeftArrowAdorner leftArrowAdorner;

        public TitleLeftArrowAdorner LeftArrowAdorner
        {
            get { return leftArrowAdorner; }
        }

        private TitleRightArrowAdorner rightArrowAdorner;

        public TitleRightArrowAdorner RightArrowAdorner
        {
            get { return rightArrowAdorner; }
        }

        private TitleUpArrowAdorner upArrowAdorner;

        public TitleUpArrowAdorner UpArrowAdorner
        {
            get { return upArrowAdorner; }
        }

        private TitleDownArrowAdorner downArrowAdorner;

        public TitleDownArrowAdorner DownArrowAdorner
        {
            get { return downArrowAdorner; }
        }

        private TitleFriendAdorner friendAdorner;

        public TitleFriendAdorner JumpLinkedAdorner
        {
            get { return friendAdorner; }
        }

        private TitleLinkAdorner linkAdorner;

        public TitleLinkAdorner LinkAdorner
        {
            get { return linkAdorner; }
        }

        private MindMapView masterView = null;

        public MindMapView MasterView
        {
            get { return masterView; }
            set { masterView = value; }
        }

        private bool isLayoutTitle = false;

        public bool IsLayoutTitle
        {
            get { return isLayoutTitle; }
            set
            {
                isLayoutTitle = value;
                if (isLayoutTitle)
                {
                    this.layoutAdorner.InvalidateVisual();
                    this.layoutAdorner.Visibility = Visibility.Visible;
                }
                else
                {
                    this.layoutAdorner.Visibility = Visibility.Collapsed;
                }
            }
        }

        private bool isSelectedTitle = false;

        public bool IsSelectedTitle
        {
            get { return isSelectedTitle; }
            set
            {
                isSelectedTitle = value;
                if (isSelectedTitle)
                {
                    this.selectedAdorner.Visibility = Visibility.Visible;
                    this.selectedAdorner.InvalidateVisual();
                }
                else
                {
                    this.selectedAdorner.Visibility = Visibility.Collapsed;
                }
                OnIsSelectedChanged(this, new MindMapTitleIsSelectedArgs() { Element = this.element, IsSelected = value, });
            }
        }

        public event EventHandler<MindMapTitleIsSelectedArgs> IsSelectedChanged;

        protected void OnIsSelectedChanged(object sender, MindMapTitleIsSelectedArgs e)
        {
            if (IsSelectedChanged != null)
            {
                IsSelectedChanged(sender, e);
            }
        }

        public bool IsFriendExist
        {
            get
            {
                if (this.element == null || this.element.Friends == null) return false;
                return this.element.Friends.Count > 0;
            }
        }

        public bool IsLeftFishBranchTitle { get; set; } = false;

        public bool IsLeftFishHeaderTitle { get; set; } = false;

        public bool IsRightFishBranchTitle { get; set; } = false;

        public bool IsRightFishHeaderTitle { get; set; } = false;

        #region 尝试寻找四周最近的标题

        /// <summary>
        /// 用于查找距离当前节点最近的节点。
        /// </summary>
        internal double Distance { get; set; }

        public bool IsTopFishBranch { get; set; } = false;

        /// <summary>
        /// 前一个同级标题。
        /// </summary>
        public MindMapTitle PreviewSibling
        {
            get
            {
                if (this.ParentTitle == null) return null;
                if (this.ParentTitle.Children == null) return null;
                var index = this.ParentTitle.Children.IndexOf(this);
                if (index < 1) return null;
                return this.ParentTitle.Children[index - 1];
            }
        }

        /// <summary>
        /// 后一个同级标题。
        /// </summary>
        public MindMapTitle NextSibling
        {
            get
            {
                if (this.ParentTitle == null) return null;
                if (this.ParentTitle.Children == null) return null;
                var index = this.ParentTitle.Children.IndexOf(this);
                if (index >= this.ParentTitle.Children.Count - 1) return null;
                return this.ParentTitle.Children[index + 1];
            }
        }

        /// <summary>
        /// 长子。
        /// </summary>
        public MindMapTitle FirstBorn
        {
            get
            {
                if (this.Children == null || this.Children.Count <= 0) return null;
                return this.Children[0];
            }
        }

        /// <summary>
        /// 幼子。
        /// </summary>
        public MindMapTitle LastBorn
        {
            get
            {
                if (this.Children == null || this.Children.Count <= 0) return null;
                return this.Children[this.Children.Count - 1];
            }
        }

        /// <summary>
        /// 左侧最近标题。用于使用上下左右键移动焦点，并使用回车键展示选中的新节点。
        /// 注意：只有在 Canvas 中才有效！
        /// </summary>
        public MindMapTitle LeftTitle
        {
            get
            {
                if (this.MasterView == null) return null;

                if (this.MasterView.DisplayView == MindMapView.ViewType.LeftFish)
                {
                    if (this.IsLeftFishHeaderTitle)
                        return null;
                    else if (this.IsLeftFishBranchTitle)
                    {
                        var preSibling = this.PreviewSibling;
                        if (preSibling != null)
                        {
                            var preLastBorn = preSibling.LastBorn;
                            if (preLastBorn != null)
                                return preLastBorn;
                            return preSibling;
                        }

                        return this.ParentTitle;
                    }
                    else
                    {
                        var preSibling = this.PreviewSibling;
                        if (preSibling != null) return preSibling;

                        return this.ParentTitle;
                    }
                }
                else if (this.MasterView.DisplayView == MindMapView.ViewType.RightFish)
                {
                    if (this.IsRightFishHeaderTitle)
                    {
                        return this.FirstBorn;
                    }
                    else if (this.IsRightFishBranchTitle)
                    {
                        var firstBorn = this.FirstBorn;
                        if (firstBorn != null)
                        {
                            return firstBorn;
                        }
                        else return this.NextSibling;
                    }
                    else
                    {
                        var nxtSibling = this.NextSibling;
                        if (nxtSibling != null) return nxtSibling;

                        if (this.ParentTitle == null) return null;
                        return this.ParentTitle.NextSibling;
                    }
                }
                else
                {
                    var titles = new List<MindMapTitle>();
                    foreach (var child in this.MasterView.MainCanvas.Children)
                    {
                        var title = child as MindMapTitle;
                        if (title == null || title == this) continue;

                        if (title.RightCenter.X < this.LeftCenter.X)
                        {
                            var w = Math.Abs(this.LeftCenter.X - title.RightCenter.X);
                            var h = Math.Abs(this.LeftCenter.Y - title.RightCenter.Y);

                            title.Distance = Math.Abs(Math.Sqrt(w * w + h * h));
                            titles.Add(title);
                        }
                    }

                    if (titles.Count <= 0) return null;
                    if (titles.Count == 1) return titles[0];

                    titles.Sort((x, y) => x.Distance.CompareTo(y.Distance));

                    return titles[0];  // 返回这些标题里最接近的一个。
                }
            }
        }

        /// <summary>
        /// 右侧最近标题。用于使用上下左右键移动焦点，并使用回车键展示选中的新节点。
        /// 注意：只有在 Canvas 中才有效！
        /// </summary>
        public MindMapTitle RightTitle
        {
            get
            {
                if (this.MasterView == null) return null;

                if (this.MasterView.DisplayView == MindMapView.ViewType.LeftFish)
                {
                    if (this.IsLeftFishHeaderTitle)
                    {
                        return this.FirstBorn;
                    }
                    else if (this.IsLeftFishBranchTitle)
                    {
                        var firstBorn = this.FirstBorn;
                        if (firstBorn != null)
                        {
                            return firstBorn;
                        }
                        else return this.NextSibling;
                    }
                    else
                    {
                        var nxtSibling = this.NextSibling;
                        if (nxtSibling != null) return nxtSibling;

                        if (this.ParentTitle == null) return null;
                        return this.ParentTitle.NextSibling;
                    }
                }
                else if (this.MasterView.DisplayView == MindMapView.ViewType.RightFish)
                {
                    if (this.IsRightFishHeaderTitle)
                        return null;
                    else if (this.IsRightFishBranchTitle)
                    {
                        var preSibling = this.PreviewSibling;
                        if (preSibling != null)
                        {
                            var preLastBorn = preSibling.LastBorn;
                            if (preLastBorn != null)
                                return preLastBorn;
                            return preSibling;
                        }

                        return this.ParentTitle;
                    }
                    else
                    {
                        var preSibling = this.PreviewSibling;
                        if (preSibling != null) return preSibling;

                        return this.ParentTitle;
                    }
                }
                else
                {
                    var titles = new List<MindMapTitle>();
                    foreach (var child in this.MasterView.MainCanvas.Children)
                    {
                        var title = child as MindMapTitle;
                        if (title == null || title == this) continue;

                        if (title.LeftCenter.X > this.RightCenter.X)
                        {
                            var w = Math.Abs(this.RightCenter.X - title.LeftCenter.X);
                            var h = Math.Abs(this.RightCenter.Y - title.LeftCenter.Y);

                            title.Distance = Math.Abs(Math.Sqrt(w * w + h * h));
                            titles.Add(title);
                        }
                    }

                    if (titles.Count <= 0) return null;
                    if (titles.Count == 1) return titles[0];

                    titles.Sort((x, y) => x.Distance.CompareTo(y.Distance));

                    return titles[0];  // 返回这些标题里最接近的一个。
                }
            }
        }

        /// <summary>
        /// 上侧最近标题。用于使用上下左右键移动焦点，并使用回车键展示选中的新节点。
        /// 注意：只有在 Canvas 中才有效！
        /// </summary>
        public MindMapTitle TopTitle
        {
            get
            {
                if (this.MasterView == null) return null;

                if (this.MasterView.DisplayView == MindMapView.ViewType.LeftFish ||
                    this.MasterView.DisplayView == MindMapView.ViewType.RightFish)
                {
                    if (this.IsLeftFishHeaderTitle || this.IsRightFishHeaderTitle)
                        return null;
                    else if (this.IsLeftFishBranchTitle || this.IsRightFishBranchTitle)
                    {
                        var preSibling = this.PreviewSibling;
                        if (preSibling != null)
                        {
                            if (preSibling.Children != null && preSibling.Children.Count > 0)
                            {
                                return preSibling.IsTopFishBranch ? preSibling.FirstBorn : preSibling.LastBorn;
                            }
                            else return preSibling;
                        }
                        else return this.ParentTitle;
                    }
                    else
                    {
                        var sibling = this.IsTopFishBranch ? this.NextSibling : this.PreviewSibling;
                        if (sibling != null) return sibling;
                        else return this.ParentTitle;
                    }
                }
                else
                {
                    var titles = new List<MindMapTitle>();
                    foreach (var child in this.MasterView.MainCanvas.Children)
                    {
                        var title = child as MindMapTitle;
                        if (title == null || title == this) continue;

                        if (title.BottomCenter.Y < this.TopCenter.Y)
                        {
                            var w = Math.Abs(this.TopCenter.X - title.BottomCenter.X);
                            var h = Math.Abs(this.TopCenter.Y - title.BottomCenter.Y);

                            title.Distance = Math.Abs(Math.Sqrt(w * w + h * h));
                            titles.Add(title);
                        }
                    }

                    if (titles.Count <= 0) return null;
                    if (titles.Count == 1) return titles[0];

                    titles.Sort((x, y) => x.Distance.CompareTo(y.Distance));

                    return titles[0];  // 返回这些标题里最接近的一个。
                }
            }
        }

        /// <summary>
        /// 下侧最近标题。用于使用上下左右键移动焦点，并使用回车键展示选中的新节点。
        /// 注意：只有在 Canvas 中才有效！
        /// </summary>
        public MindMapTitle BottomTitle
        {
            get
            {
                if (this.MasterView == null) return null;

                if (this.MasterView.DisplayView == MindMapView.ViewType.LeftFish ||
                    this.MasterView.DisplayView == MindMapView.ViewType.RightFish)
                {
                    if (this.IsLeftFishHeaderTitle || this.IsRightFishHeaderTitle)
                        return this.FirstBorn;
                    else if (this.IsLeftFishBranchTitle || this.IsRightFishBranchTitle)
                    {
                        if (this.Children != null && this.Children.Count > 0)
                            return this.IsTopFishBranch ? this.LastBorn : this.FirstBorn;

                        return this.NextSibling;
                    }
                    else
                    {
                        var sibling = this.IsTopFishBranch ? this.PreviewSibling : this.NextSibling;
                        if (sibling != null) return sibling;
                        else
                        {
                            var parentTitle = this.ParentTitle;
                            if (parentTitle == null) return null;
                            var nextParentSibling = parentTitle.NextSibling;
                            if (nextParentSibling != null) return nextParentSibling;

                            return null;
                        }
                    }
                }
                else
                {
                    var titles = new List<MindMapTitle>();
                    foreach (var child in this.MasterView.MainCanvas.Children)
                    {
                        var title = child as MindMapTitle;
                        if (title == null || title == this) continue;

                        if (title.TopCenter.Y > this.BottomCenter.Y)
                        {
                            var w = Math.Abs(this.BottomCenter.X - title.TopCenter.X);
                            var h = Math.Abs(this.BottomCenter.Y - title.TopCenter.Y);

                            title.Distance = Math.Abs(Math.Sqrt(w * w + h * h));
                            titles.Add(title);
                        }
                    }

                    if (titles.Count <= 0) return null;
                    if (titles.Count == 1) return titles[0];

                    titles.Sort((x, y) => x.Distance.CompareTo(y.Distance));

                    return titles[0];  // 返回这些标题里最接近的一个。
                }
            }
        }

        #endregion

        private double left = 0;
        /// <summary>
        /// 这个属性的值是不是自动更新的。需要注意。
        /// </summary>
        public double Left
        {
            get { return left; }
            set { left = value; }
        }

        private double top = 0;
        /// <summary>
        /// 这个属性的值是不是自动更新的。需要注意。
        /// </summary>
        public double Top
        {
            get { return top; }
            set { top = value; }
        }

        public Point TopLeft
        {
            get { return new Point(this.left, this.top); }
        }

        public Point TopRight
        {
            get { return new Point(this.left + this.ActualWidth, this.top); }
        }

        public Point BottomLeft
        {
            get { return new Point(this.left, this.top + this.ActualHeight); }
        }

        public Point BottomRight
        {
            get { return new Point(this.left + this.ActualWidth, this.top + this.ActualHeight); }
        }

        public Point LeftCenter
        {
            get { return new Point(this.left, this.top + this.ActualHeight / 2); }
        }

        public Point TopCenter
        {
            get { return new Point(this.left + this.ActualWidth / 2, this.top); }
        }

        public Point RightCenter
        {
            get { return new Point(this.left + this.ActualWidth, this.top + this.ActualHeight / 2); }
        }

        public Point BottomCenter
        {
            get { return new Point(this.left + this.ActualWidth / 2, this.top + this.ActualHeight); }
        }

        public Point Center
        {
            get { return new Point(this.Left + this.ActualWidth / 2, this.top + this.ActualHeight / 2); }
        }

        public Point LinkPointStart { get; set; }

        public Point LinkPoint1 { get; set; }

        public Point LinkPoint2 { get; set; }

        public Point LinkPoint3 { get; set; }

        public Point GetLinkCenterPoint()
        {
            return new Point(LinkPointStart.X + (LinkPoint3.X - LinkPointStart.X) / 2, LinkPointStart.Y + (LinkPoint3.Y - LinkPointStart.Y) / 2);
        }

        /// <summary>
        /// 标题的角色。会影响到明暗主题下标题的默认底色。
        /// </summary>
        public enum TitleRole
        {
            /// <summary>
            /// 所有上级标题。
            /// </summary>
            AncestorsTitle,
            /// <summary>
            /// 当前演示的标题。
            /// </summary>
            DisplayCenterTitle,
            /// <summary>
            /// 子级标题。
            /// </summary>
            ChildTitle,
        }

        private TitleRole role = TitleRole.DisplayCenterTitle;
        /// <summary>
        /// 当前标题演示时扮演的角色。
        /// </summary>
        public TitleRole Role
        {
            get { return this.role; }
            set
            {
                this.role = value;
                RefreshTitleBackground();
            }
        }

        /// <summary>
        /// 连接线，指向父节点标题。
        /// </summary>
        private Path linkToParentPath = new Path() { Opacity = 0, StrokeThickness = 3, StrokeLineJoin = PenLineJoin.Round, };

        public Path LinkToParentPath
        {
            get { return linkToParentPath; }
        }

        private BezierSegment linkToParentBezierSegment = new BezierSegment() { IsSmoothJoin = true, };

        public BezierSegment LinkToParentBezierSegment
        {
            get { return linkToParentBezierSegment; }
        }

        private PathFigure linkToParentPathFigure = new PathFigure();

        public PathFigure LinkToParentPathFigure
        {
            get { return linkToParentPathFigure; }
        }

        public MindMapTitle ParentTitle { get; internal set; }

        private PathGeometry linkToParentPathGeometry = new PathGeometry();

        public void DemonstratChildResourceTitles()
        {

        }
    }

    /// <summary>
    /// 标题专用，保证标题内部的文本都显示在标题内部。
    /// </summary>
    public class DefaultFontSizeToPaddingConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            double fontsize = (double)value;
            double h = fontsize / 2;
            double q = fontsize / 4;
            return new Thickness(h, q, h, q);
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            Thickness padding = (Thickness)value;
            return padding.Left * 2;
        }
    }

    public class MindMapTitleIsSelectedArgs : EventArgs
    {
        public TreeElement Element { get; set; }
        public bool IsSelected { get; set; }
    }

    public class HeightToRadiusConverter : IValueConverter
    {

        #region IValueConverter 成员

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            double height = (double)value;
            return height / 2;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            double radius = (double)value;
            return radius * 2;
        }

        #endregion
    }
}
